using System.Text.RegularExpressions;
using Newtonsoft.Json;

namespace SmartCustomerService.Web.Services;

public interface ISimpleRetrievalService
{
	List<string> RetrieveRelevantSnippets(string query, int maxItems = 5);
}

public class SimpleRetrievalService : ISimpleRetrievalService
{
	private readonly string _dataDirectory;
	private readonly object _lockObj = new();
	private List<KnowledgeItem> _knowledge = new();

	public SimpleRetrievalService(IWebHostEnvironment env, ILogger<SimpleRetrievalService> logger)
	{
		_dataDirectory = Path.Combine(env.ContentRootPath, "Data");
		Directory.CreateDirectory(_dataDirectory);

		// Load knowledge.json if exists
		var jsonPath = Path.Combine(_dataDirectory, "knowledge.json");
		if (File.Exists(jsonPath))
		{
			try
			{
				var json = File.ReadAllText(jsonPath);
				var items = JsonConvert.DeserializeObject<List<KnowledgeItem>>(json) ?? new();
				_knowledge = items
					.Where(i => !string.IsNullOrWhiteSpace(i.Title) || !string.IsNullOrWhiteSpace(i.Content))
					.ToList();
			}
			catch (Exception ex)
			{
				logger.LogWarning(ex, "Failed to load knowledge.json");
			}
		}
	}

	public List<string> RetrieveRelevantSnippets(string query, int maxItems = 5)
	{
		if (string.IsNullOrWhiteSpace(query) || _knowledge.Count == 0)
		{
			return new List<string>();
		}

		var terms = Tokenize(query);
		var ranked = _knowledge
			.Select(k => new
			{
				Item = k,
				Score = Score(k, terms)
			})
			.Where(x => x.Score > 0)
			.OrderByDescending(x => x.Score)
			.Take(maxItems)
			.Select(x => $"【{x.Item.Title}】\n{x.Item.Content}")
			.ToList();

		return ranked;
	}

	private static int Score(KnowledgeItem item, List<string> terms)
	{
		var text = ($"{item.Title} {item.Content}").ToLowerInvariant();
		var score = 0;
		foreach (var t in terms)
		{
			if (text.Contains(t)) score += 2;
		}
		return score;
	}

	private static List<string> Tokenize(string text)
	{
		text = text.ToLowerInvariant();
		text = Regex.Replace(text, "[^0-9a-z\u4e00-\u9fa5]+", " ");
		return text.Split(' ', StringSplitOptions.RemoveEmptyEntries)
			.Where(s => s.Length >= 2)
			.Take(20)
			.ToList();
	}

	private class KnowledgeItem
	{
		public string Title { get; set; } = string.Empty;
		public string Content { get; set; } = string.Empty;
	}
}
